package crack_sda2;

import fem2.AbstractStructuralStaticDemo;
import fem2.Element;
import fem2.MaterialModel;
import fem2.Mesh;
import fem2.MeshPart;
import fem2.Model;
import fem2.Node;
import fem2.Observer;
import fem2.StringUtilities;
import fem2.material.cohesive_law2.CohesiveLaw;
import fem2.observer.GidCrackObserver2;
import fem2.observer.GmshCrackObserver2;
import fem2.observer.ResistantGraphicalObserver;
import fem2.observer.TimeStepObserver;
import fem2.strategies.Strategy;

/**
 * Abstract class for all structural demo with homogeneous material and crack
 * elements also cohesive law
 * 
 * @author hbui
 * 
 */
public abstract class AbstractStructuralCrackDemo extends AbstractStructuralStaticDemo {

	/**
	 * create cohesive law
	 * 
	 * @return
	 */
	public abstract CohesiveLaw createCohesiveLaw(Model m);

	@Override
	public Element createElement(MeshPart mp, MaterialModel mm) {
		throw new Error("please call createElement with cohesive law instead");
	}

	/**
	 * specify element associated with model
	 * 
	 * @param mp
	 * @param mm
	 * @param cl
	 * @return
	 */
	public abstract Element createElement(MeshPart mp, MaterialModel mm, CohesiveLaw cl);

	@Override
	public Model createModel() {

		Mesh mesh = createMesh();

		/*
		 * set the number of fields for structural problem
		 */
		mesh.setNumberOfFields(mesh.getDimension());

		Model m = new Model(mesh);

		MaterialModel mm = createMaterial(m);

		CohesiveLaw cl = createCohesiveLaw(m);

		int dim = mesh.getDimension();
		if (dim == 1) {
			for (int i = 0; i < mesh.countEdges(); i++) {
				Element e = createElement(mesh.getEdge(i), mm, cl);
				m.addElement(e);
			}
		} else if (dim == 2) {
			for (int i = 0; i < mesh.countFaces(); i++) {
				Element e = createElement(mesh.getFace(i), mm, cl);
				m.addElement(e);
			}
		} else if (dim == 3) {
			for (int i = 0; i < mesh.countBlocks(); i++) {
				Element e = createElement(mesh.getBlock(i), mm, cl);
				m.addElement(e);
			}
		} else {
			throw new Error("invalid dimension");
		}

		m = createConditions(m);

		return m;
	}

	/**
	 * add nodes for resistant observer
	 * 
	 * @param m
	 * @return
	 */
	public Node[] getNodesForResistantObserver(Model m) {
		return null;
	}

	@Override
	public void addObservers(Model m, Strategy s, TimeStepObserver o) {
		addFundamentalObservers(m, s, o);
		addObserversForCrackProblem(m, s, o);
	}

	/**
	 * @param m
	 * @param s
	 * @param o
	 */
	protected void addObserversForCrackProblem(Model m, Strategy s, TimeStepObserver o) {
		String meshName = StringUtilities.getFileName(meshFileName);

		Observer co1 = new GidCrackObserver2(m, o, projectDir, projectName, meshName);
		Observer co2 = new GmshCrackObserver2(m, projectDir + '/' + projectName + '/' + meshName
				+ "-with-crack.gmsh.msh");

		s.addObserver(co1);
		s.addObserver(co2);

		Node[] nodes = getNodesForResistantObserver(m);
		if (nodes != null) {
			Observer ro1 = new ResistantGraphicalObserver(m, s, nodes);
			s.addObserver(ro1);
		}
	}

}
